home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / MAIL / ALIAS.C < prev    next >
C/C++ Source or Header  |  1992-11-22  |  16KB  |  415 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    alias.c                                                         */
  3. /*                                                                    */
  4. /*    Smart routing and alias routines for pcmail.                    */
  5. /*                                                                    */
  6. /*    Copyright (C) 1989 Andrew H. Derbyshire                         */
  7. /*                                                                    */
  8. /*    Additional code                                                 */
  9. /*       Copyright (c) Richard H. Lamb 1985, 1986, 1987               */
  10. /*       Changes Copyright (c) Stuart Lynne 1987                      */
  11. /*                                                                    */
  12. /*    Updates:                                                        */
  13. /*                                                                    */
  14. /*    02 Oct 89   Alter large strings/structures to use               */
  15. /*                malloc()/free()                              ahd    */
  16. /*    08 Feb 90   Correct failure of ExtractAddress to return         */
  17. /*                non-names                                    ahd    */
  18. /*    18 Mar 90   Move checkname() and associated routines into       */
  19. /*                hostable.c                                   ahd    */
  20. /*    22 Apr 90   Modify user_at_node to correctly handle .UUCP       */
  21. /*                alias on local host.                         ahd    */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. /*
  25.  *    $Id: ALIAS.C 1.2 1992/11/22 21:06:14 ahd Exp $
  26.  *
  27.  *    $Log: ALIAS.C $
  28.  * Revision 1.2  1992/11/22  21:06:14  ahd
  29.  * Use strpool for memory allocation
  30.  *
  31.  */
  32.  
  33. #include <ctype.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <sys/types.h>
  38.  
  39. #ifndef __TURBOC__
  40. #include <search.h>
  41. #endif
  42.  
  43. #include "lib.h"
  44. #include "hostable.h"
  45. #include "security.h"
  46. #include "usertabl.h"
  47. #include "hlib.h"
  48. #include "alias.h"
  49. #include "address.h"
  50.  
  51. static size_t AliasCount = 0;
  52.  
  53. static struct AliasTable *alias = NULL;
  54.  
  55. int nickcmp( const void *a, const void *b );
  56.  
  57. static size_t LoadAliases( void ) ;
  58.  
  59. currentfile();
  60.  
  61. /*--------------------------------------------------------------------*/
  62. /*    I n i t R o u t e r                                             */
  63. /*                                                                    */
  64. /*    Verify, initialize the global routing data                      */
  65. /*--------------------------------------------------------------------*/
  66.  
  67. boolean InitRouter()
  68. {
  69.    boolean success = TRUE;       /* Assume the input data is good       */
  70.    struct HostTable *Hptr;
  71.  
  72. /*--------------------------------------------------------------------*/
  73. /*          Verify that the user gave us a good name server           */
  74. /*--------------------------------------------------------------------*/
  75.  
  76.    Hptr = checkreal(E_mailserv);
  77.    if (Hptr == BADHOST)
  78.    {
  79.       printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
  80.          E_mailserv);
  81.       success = FALSE;
  82.    }
  83.    else if (Hptr->hstatus == localhost)  /* local system?     */
  84.    {
  85.       printmsg(0,"'%s' is name of this host and cannot be mail server",
  86.             E_mailserv);
  87.       success = FALSE;
  88.    }
  89.  
  90. /*--------------------------------------------------------------------*/
  91. /*                          Return to caller                          */
  92. /*--------------------------------------------------------------------*/
  93.  
  94.    return success;
  95. } /* InitRouter */
  96.  
  97. /*--------------------------------------------------------------------*/
  98. /*    E x t r a c t N a m e                                           */
  99. /*                                                                    */
  100. /*    Returns full name of user, and returns address if name          */
  101. /*    is not available.                                               */
  102. /*--------------------------------------------------------------------*/
  103.  
  104. void ExtractName(char *result, char *column)
  105. {
  106.       static int recursion = 0;
  107.  
  108.       recursion++;
  109.  
  110.       printmsg((recursion > 2) ? 1:8,
  111.             "ExtractName: Getting name from '%s'",column);
  112.  
  113.       ExtractAddress(result, column, TRUE);  /* Get the full name    */
  114.       if (!strlen(result))       /* Did we get the name?             */
  115.       {                          /* No --> Get the e-mail address    */
  116.          char addr[MAXADDR];
  117.          char path[MAXADDR];
  118.          char node[MAXADDR];
  119.          char *fullname;
  120.  
  121.          ExtractAddress(addr,column, FALSE);
  122.          user_at_node(addr,path,node,result);
  123.                                  /* Reduce address to basics */
  124.          fullname = AliasByAddr(node,result);
  125.          if (fullname == NULL)
  126.          {
  127.             strcat(result,"@");
  128.             strcat(result,node);
  129.          }
  130.          else
  131.             strcpy(result,fullname);
  132.       }
  133.  
  134.       printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
  135.  
  136.       recursion--;
  137.  
  138.       return;
  139. }  /*ExtractName*/
  140.  
  141. /*--------------------------------------------------------------------*/
  142. /*    B u i l d A d d r e s s                                         */
  143. /*                                                                    */
  144. /*    Builds a standard address format, with aliasing as              */
  145. /*    required.                                                       */
  146. /*--------------------------------------------------------------------*/
  147.  
  148. void BuildAddress(char *result, const char *input)
  149. {
  150.    char addr[MAXADDR];
  151.    char name[MAXADDR];
  152.    char user[MAXADDR];
  153.    char path[MAXADDR];
  154.    char node[MAXADDR];
  155.    char *fulladdr;
  156.  
  157. /*--------------------------------------------------------------------*/
  158. /*   It must be a real address, possibly with a name attached; get    */
  159. /*   the address portion, break the address into user and node, and   */
  160. /*   then see if we know the person by address                        */
  161. /*--------------------------------------------------------------------*/
  162.  
  163.       ExtractAddress(addr,input,FALSE);   /* Get user e-mail addr    */
  164.       user_at_node(addr,path,node,user);  /* Break address down      */
  165.  
  166.       fulladdr = AliasByAddr(node,user);  /* Alias for the address?  */
  167.       if (fulladdr != NULL)            /* Yes --> Use it             */
  168.       {
  169.          strcpy(result,fulladdr);
  170.          return;
  171.       } /* if */
  172.  
  173. /*--------------------------------------------------------------------*/
  174. /*   We don't know the address yet; get the name the user provided,   */
  175. /*   and then normalize the address                                   */
  176. /*--------------------------------------------------------------------*/
  177.  
  178.       ExtractAddress(name,input,TRUE);    /* Also get their name     */
  179.  
  180.       if (strlen(name))             /* Did we find a name for user?  */
  181.       {                             /* Yes --> Return it             */
  182.          char *s = strchr(node, '.');
  183.          if ((s == NULL) || equalni( s, ".UUCP", 5))
  184.                                     /* Simple name or UUCP domain?   */
  185.          {                          /* Yes--> Use original address   */
  186.             size_t pathlen = strlen(path);/* Save len of orig path   */
  187.             if ((pathlen > strlen(addr)) &&
  188.                 (!equal(node,path)) && /* Target not a known host?   */
  189.                 equaln(addr,path, strlen(path)) && /* & host starts  */
  190.                 (addr[pathlen] == '!'))   /* ...the address?         */
  191.                fulladdr = &addr[pathlen + 1];   /* Yes --> Drop it   */
  192.             else
  193.                fulladdr = addr;  /* No --> Use full address          */
  194.             sprintf(result,"(%s) %s", name, addr);
  195.          } /* (strchr(node, '.') == NULL) */
  196.          else                    /* No --> Use RFC-822 format        */
  197.             sprintf(result,"\"%s\" <%s@%s>", name, user, node);
  198.       } /* if strlen(name) */
  199.       else
  200.          strcpy(result,addr);    /* No name, just use the original   */
  201. } /* BuildAddress */
  202.  
  203.  
  204. /*--------------------------------------------------------------------*/
  205. /*    A l i a s B y N i c k                                           */
  206. /*                                                                    */
  207. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  208. /*    if alias found and has address, otherwise FALSE.                */
  209. /*--------------------------------------------------------------------*/
  210.  
  211. char *AliasByNick(const char *nick)
  212. {
  213.    int   upper;
  214.    int   lower;
  215.  
  216.    if (!AliasCount)
  217.       AliasCount = LoadAliases();
  218.  
  219.    upper = AliasCount - 1;
  220.    lower = 0;
  221.  
  222.    while (upper >= lower)
  223.    {
  224.       int midpoint;
  225.       int hit;
  226.  
  227.       midpoint = ( upper + lower ) / 2;
  228.       hit = stricmp(nick,alias[midpoint].anick);
  229.       if (!hit)
  230.          return alias[midpoint].afull;
  231.       if ( hit > 0 )
  232.          lower = midpoint + 1;
  233.       else
  234.          upper = midpoint - 1;
  235.    }
  236.    return NULL;
  237. }
  238.  
  239.  
  240. /*--------------------------------------------------------------------*/
  241. /*    A l i a s B y A d d r                                           */
  242. /*                                                                    */
  243. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  244. /*    if alias found and has address, otherwise FALSE                 */
  245. /*--------------------------------------------------------------------*/
  246.  
  247. char *AliasByAddr(const char *node, const char *user)
  248. {
  249.    size_t current = 0;
  250.  
  251.    if (!AliasCount)
  252.       AliasCount = LoadAliases();
  253.  
  254.    while (current < AliasCount)
  255.    {
  256.       int hit;
  257.  
  258.       hit = stricmp(node,alias[current].anode);
  259.       if (!hit)
  260.       {
  261.          hit = stricmp(user,alias[current].auser);
  262.          if (!hit)
  263.             return alias[current].afull;
  264.       }
  265.       current++;
  266.    }
  267.    return NULL;
  268.  
  269. }
  270.  
  271.  
  272. /*--------------------------------------------------------------------*/
  273. /*    L o a d A l i a s e s                                           */
  274. /*                                                                    */
  275. /*    Initializes the address alias table; returns number of aliases  */
  276. /*    loaded                                                          */
  277. /*--------------------------------------------------------------------*/
  278.  
  279. size_t LoadAliases(void)
  280. {
  281.    FILE *ff;
  282.    char buf[BUFSIZ];
  283.    char *token;
  284.    size_t   elements = 0;
  285.    size_t   max_elements = UserElements + 20;
  286.    size_t   subscript;
  287.    struct AliasTable *hit;           /* temporary pointer for searching  */
  288.    struct AliasTable target;
  289.  
  290.  
  291.    checkuser( E_mailbox ); /* Force the table to be loaded           */
  292.    alias = calloc(max_elements, sizeof(*alias));
  293.    checkref(alias);
  294.  
  295. /*--------------------------------------------------------------------*/
  296. /*                   Actually load the alias table                    */
  297. /*--------------------------------------------------------------------*/
  298.  
  299.    if (E_aliases != NULL )    /* Did the user specify aliases file?  */
  300.    {
  301.  
  302.       ff = FOPEN(E_aliases, "r", TEXT);
  303.       if (ff == NULL)
  304.       {
  305.          printerr(E_aliases);
  306.          return elements;
  307.       } /* if */
  308.  
  309.       while (! feof(ff))
  310.       {
  311.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  312.             break;                  /* Exit if end of file              */
  313.          token = strtok(buf," \t\n");
  314.          if (token == NULL)         /* Any data?                        */
  315.             continue;               /* No --> read another line         */
  316.          if (token[0] == '#')
  317.             continue;                  /* Line is a comment; loop again */
  318.  
  319.          /* Add the alias to the table.  Note that we must add the nick */
  320.          /* to the table ourselves (rather than use lsearch) because    */
  321.          /* we must make a copy of the string; the *token we use for    */
  322.          /* the search is in the middle of our I/O buffer!              */
  323.          /*
  324.          /* I was burned, _you_ have been warned.                       */
  325.  
  326.          target.anick = token;
  327.  
  328.          hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
  329.              nickcmp);
  330.          if (hit == NULL)
  331.          {
  332.             char node[MAXADDR];
  333.             char user[MAXADDR];
  334.             char path[MAXADDR];
  335.             char addr[MAXADDR];
  336.             char *eos;
  337.  
  338.             if (elements == max_elements)
  339.             {
  340.                 max_elements = max_elements * 2;
  341.                 alias = realloc(alias, max_elements * sizeof(*alias));
  342.                 checkref(alias);
  343.             }
  344.  
  345.             alias[elements].anick = newstr(token);
  346.             token = strtok(NULL,"");    /* Get rest of string         */
  347.  
  348.             while ( strlen(token) && isspace(*token))
  349.                token++;
  350.             eos = token + strlen(token) - 1;
  351.             while ( strlen(token) && isspace(*eos))
  352.             {
  353.                *eos = '\0';
  354.                eos--;
  355.             }
  356.  
  357.             alias[elements].afull = newstr(token);
  358.             ExtractAddress(addr,alias[elements].afull,FALSE);
  359.             user_at_node(addr,path,node,user);
  360.             alias[elements].anode = newstr(node);
  361.             alias[elements].auser = newstr(user);
  362.             elements += 1;
  363.          }
  364.          else
  365.             printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
  366.       }
  367.       fclose(ff);
  368.    } /* if (E_aliases != NULL ) */
  369.  
  370. /*--------------------------------------------------------------------*/
  371. /*           Add the local users as final aliases in table            */
  372. /*--------------------------------------------------------------------*/
  373.  
  374.    alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
  375.                               /* Resize table to final known size    */
  376.    checkref(alias);
  377.  
  378.    for ( subscript = 0; subscript < UserElements; subscript++, elements++)
  379.    {
  380.       alias[elements].anick = "";   /* No nickname, only good for addr  */
  381.       if (bflag[F_BANG])
  382.          sprintf(buf, "(%s) %s!%s",
  383.                users[subscript].realname, E_fdomain,
  384.                users[subscript].uid);
  385.       else
  386.          sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
  387.                users[subscript].uid, E_fdomain );
  388.       alias[elements].afull = newstr(buf);
  389.       alias[elements].anode = E_nodename;
  390.       alias[elements].auser = users[subscript].uid;
  391.    } /* for */
  392.  
  393. /*--------------------------------------------------------------------*/
  394. /*                         Now sort the table                         */
  395. /*--------------------------------------------------------------------*/
  396.  
  397.    qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
  398.  
  399.    return (elements) ;
  400. } /*LoadAliases*/
  401.  
  402.  
  403. /*--------------------------------------------------------------------*/
  404. /*   n i c k c m p                                                    */
  405. /*                                                                    */
  406. /*   Accepts indirect pointers to two strings and compares them using */
  407. /*   stricmp (case insensitive string compare)                        */
  408. /*--------------------------------------------------------------------*/
  409.  
  410. int nickcmp( const void *a, const void *b )
  411. {
  412.    return stricmp(((struct AliasTable *)a)->anick,
  413.          ((struct AliasTable *)b)->anick);
  414. }  /*nickcmp*/
  415.